package com.unionftech.common.aspectj

import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import com.unionftech.common.permissions.PermissionListener
import com.unionftech.common.permissions.PermissionUtils
import com.unionftech.common.utils.LogUtils
import org.aspectj.lang.ProceedingJoinPoint
import org.aspectj.lang.annotation.Around
import org.aspectj.lang.annotation.Aspect
import org.aspectj.lang.annotation.Pointcut
import org.aspectj.lang.reflect.MethodSignature
import kotlin.math.truncate

@Aspect
class PermissionRequestAspect {
    @Pointcut("execution(@com.unionftech.common.aspectj.PermissionRequest * *(..))")
    fun permissionRequestPointCut() {
    }

    @Around("permissionRequestPointCut() && @annotation(PermissionRequest)")
    @Throws(Throwable::class)
    fun aroundPermissionPoint(joinPoint: ProceedingJoinPoint): Any? {
        var result: Any? = null
        //获取签名方法
        val methodSignature = joinPoint.signature as MethodSignature
        //获取方法的注解的值
        val value =
            methodSignature.method.getAnnotation(PermissionRequest::class.java)?.permissions as? Array<*>
        val permissions = value?.map {
            LogUtils.d("用户请求的权限：$it")
            it as String
        }
        getActivity(joinPoint)?.also { activity ->
            permissions?.also {
                PermissionUtils.getInstance()
                    .request(
                        activity,
                        it.toTypedArray(),
                        isShowTipDialog = true,
                        object : PermissionListener() {
                            override fun accept() {
                                result = joinPoint.proceed()
                            }
                        })
            }
        }
        return result
    }

    private fun getActivity(joinPoint: ProceedingJoinPoint): FragmentActivity? {
        var activity: FragmentActivity?
        val joinThis = joinPoint.`this`
        activity = findActivity(joinThis)
        if (activity == null) {
            val args = joinPoint.args
            if (args != null && args.isNotEmpty()) {
                for (arg in args) {
                    activity = findActivity(arg)
                    if (activity != null) {
                        break
                    }
                }
            }
        }
        return activity
    }

    private fun findActivity(obj: Any): FragmentActivity? {
        return when (obj) {
            is FragmentActivity -> {
                obj
            }

            is Fragment -> {
                obj.activity as FragmentActivity
            }

            else -> {
                null
            }
        }
    }
}